"""
Author : Tim Tucker
Description : Tool for associate/unassociate torrent file with the client
"""

import sys
import os
import wx

from BitTornado.__init__ import product_name

if (sys.platform[:3] == 'win'):
    import _winreg

    # short for PyHKEY from "_winreg" module
    HKCR = _winreg.HKEY_CLASSES_ROOT

    def removeKeys(keys):
        """
        Remove a set of keys from the registry
        """
        for _key_name in keys:
            try:
                # delete desired Windows registry key
                _winreg.DeleteKey(HKCR, _key_name)
            except EnvironmentError:
                return False;
            
    def addKeys(keys):
        """
        Add a set of keys to the registry
        """
        for _key_name, _value_name, _value_data, _value_type in keys:
            try:
                # Create desired key in Windows registry
                _client_key = _winreg.CreateKey(HKCR, _key_name)
            except EnvironmentError:
                return False;
            # set desired value in created Windows registry key
            _winreg.SetValueEx(_client_key, _value_name, 0, _value_type, _value_data)
            # close Windows registry key
            _winreg.CloseKey(_client_key)
            
        return True


################################################################

class RegChecker:
    """
    Used to check whether or not the client is associated as the
    default BitTorrent application
    """
    def __init__(self, utility):
        
        if (sys.platform[:3] != 'win'):
            return
        
        clientpath = os.path.join(utility.getPath(), product_name + ".exe")
        iconpath = os.path.join(utility.getPath(), "torrenticon.ico")
    
        # tuple (array) with key to register
        self.reg_data = [ (r".torrent", "", "bittorrent", _winreg.REG_SZ), 
                          (r".torrent", "Content Type", r"application/x-bittorrent", _winreg.REG_SZ), 
                          (r"MIME\Database\Content Type\application/x-bittorrent", "Extension", ".torrent", _winreg.REG_SZ), 
                          (r"bittorrent", "", "TORRENT File", _winreg.REG_SZ), 
                          (r"bittorrent\DefaultIcon", "", iconpath, _winreg.REG_SZ), 
                          (r"bittorrent", "EditFlags", chr(0)+chr(0)+chr(1)+chr(0), _winreg.REG_BINARY), 
                          (r"bittorrent\shell", "", "open", _winreg.REG_SZ), 
                          (r"bittorrent\shell\open\command", "", "\"" + clientpath + "\" \"%1\"", _winreg.REG_SZ)]
        self.reg_data_delete = [ (r"bittorrent\shell\open\ddeexec") ]
    
        # tuple (array) with key to delete    
        self.unreg_data = [ (r"bittorrent\shell\open\command"), 
                            (r"bittorrent\shell\open"), 
                            (r"bittorrent\shell"), 
                            (r"bittorrent"), 
                            (r"MIME\Database\Content Type\application/x-bittorrent"), 
                            (r".torrent") ]

    def testRegistry(self):
        """
        Test Windows registry to see if key & value exist
        """
        if (sys.platform[:3] != 'win'):
            return False
            
        key_name, value_name, value_data, value_type = self.reg_data[7]

        try:
            # test that shell/open association with the client exist
            _client_key = _winreg.OpenKey(HKCR, key_name, 0, _winreg.KEY_READ)
            _value_data, _value_type = _winreg.QueryValueEx(_client_key, value_name)
            _winreg.CloseKey(_client_key)
                    
            _value_data = os.path.normcase(_value_data)
            value_data = os.path.normcase(value_data)
            
            if _value_data != value_data:
                # association with the client don't exist
                return False
        except:
            # error, test failed, key don't exist
            # (could also indicate a unicode error)
            return False
        
        # If the client is registred, remove keys (ddeexec) that may interfere:
        removeKeys(self.reg_data_delete)
            
        return True

    def updateRegistry(self, register = True):
        """
        Either register or unregister the client from as the default handler
        for .torrent files
        """
        if (sys.platform[:3] != 'win'):
            return False

        if register:
            return self.registerClient()
        else:
            return self.unregisterClient()

    def registerClient(self):
        """
        Register the client as the handler for .torrent files in the Windows registry
        """
        if (sys.platform[:3] != 'win'):
            return False

        # if the client is already registered,
        # we don't need to do anything
        if self.testRegistry():
            return

        # "for" loop to get variable from tuple
        success = addKeys(self.reg_data)
        if not success:
            return False

        # delete ddeexec key
        success = removeKeys(self.reg_data_delete)
        if not success:
            return False

        return True

    def unregisterClient(self):
        """
        Unregister the client as the handler for .torrent files in the Windows registry
        """
        if (sys.platform[:3] != 'win'):
            return False
            
        # if the client isn't already registered,
        # we don't need to do anything
        if not self.testRegistry():
            return

        # get variable for key deletion from tuple
        success = removeKeys(self.unreg_data)
        if not success:
            return False

        return True

################################################################

class RegCheckDialog(wx.Dialog):
    """
    Prompts to associate ABC with .torrent files if it is not
    already associated with them
    """
    def __init__(self, parent):
        wx.Dialog.__init__(self, parent, -1, _('Associate with .torrent files'))

        outerbox = wx.BoxSizer(wx.VERTICAL)

        outerbox.Add(wx.StaticText(self, -1,  _('This client is not currently associated with .torrent files\nDo you wish to use this client to open .torrent files?')), 0, wx.ALIGN_LEFT|wx.ALL, 5)
               
        self.yesbtn = wx.Button(self, wx.ID_YES, _('Yes'))
        self.nobtn = wx.Button(self, wx.ID_NO, _('No'))
        self.cancelbtn = wx.Button(self, wx.ID_CANCEL, _('Cancel'))

        buttonbox = wx.BoxSizer(wx.HORIZONTAL)
        buttonbox.Add(self.yesbtn, 0, wx.ALL, 5)
        buttonbox.Add(self.nobtn, 0, wx.ALL, 5)
        buttonbox.Add(self.cancelbtn, 0, wx.ALL, 5)
        
        outerbox.Add( buttonbox, 0, wx.ALIGN_CENTER)

        self.SetAutoLayout(True)
        self.SetSizerAndFit(outerbox)

        self.Bind(wx.EVT_BUTTON, self._onYES, id = wx.ID_YES)
        self.Bind(wx.EVT_BUTTON, self._onNO, id = wx.ID_NO)
        
    def _onYES(self, event = None):
        self._apply(True)
        self.EndModal(wx.ID_YES)
        
    def _onNO(self, event = None):
        self._apply(False)
        self.EndModal(wx.ID_NO)
        
    def _apply(self, register):
        utility.regchecker.updateRegistry(register)
        utility.config.Write('associate', register, "boolean")
        utility.config.Flush()
